package com.liaoyifan.core.config;

import com.liaoyifan.core.constant.Constants;
import com.liaoyifan.core.constant.Properties;
import com.liaoyifan.core.enums.CoreEnum;
import com.liaoyifan.core.opera.CoreEnumTypeHandler;
import com.liaoyifan.core.util.SqlParser;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.dialect.DbType;
import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.spring.FlexSqlSessionFactoryBean;
import java.time.LocalDate;
import java.time.LocalDateTime;
import javax.sql.DataSource;
import org.apache.ibatis.logging.log4j2.Log4j2Impl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.LocalDateTimeTypeHandler;
import org.apache.ibatis.type.LocalDateTypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

@SuppressWarnings("unused")
@Configuration
@ConditionalOnProperty(name = Properties.MYBATIS_FLEX_ENABLE, havingValue = Constants.TRUE)
public class MyBatisFlexConfiguration {

    @Autowired
    @Qualifier("dataSource") private DataSource dataSource;

    @Bean("sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        FlexSqlSessionFactoryBean factory = new FlexSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setMapperLocations(
                new PathMatchingResourcePatternResolver()
                        .getResources(
                                ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                                        + "/mapper/**/*.xml"));
        FlexConfiguration configuration = new FlexConfiguration();
        configuration.setLogImpl(Log4j2Impl.class);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        typeHandlerRegistry.register(CoreEnum.class, CoreEnumTypeHandler.class);
        typeHandlerRegistry.register(LocalDateTime.class, LocalDateTimeTypeHandler.class);
        typeHandlerRegistry.register(LocalDate.class, LocalDateTypeHandler.class);
        factory.setConfiguration(configuration);
        FlexGlobalConfig globalConfig = FlexGlobalConfig.getDefaultConfig();
        FlexGlobalConfig.KeyConfig keyConfig = new FlexGlobalConfig.KeyConfig();
        keyConfig.setKeyType(KeyType.Auto);
        globalConfig.setKeyConfig(keyConfig);
        globalConfig.setDbType(DbType.MYSQL);
        globalConfig.setPrintBanner(false);
        FlexGlobalConfig.setDefaultConfig(globalConfig);
        AuditManager.setMessageCollector(
                message -> {
                    Logger logger = LogManager.getLogger(message.getStmtId());
                    logger.info("SQL: {}", SqlParser.compress(message.getFullSql()));
                    logger.info(
                            "Count: {}, Duration: {}ms",
                            message.getQueryCount(),
                            message.getElapsedTime());
                });
        AuditManager.setAuditEnable(true);
        return factory.getObject();
    }
}
